package com.archeocs.figone.lib;

//Author:
//Miłosz Pigłas, Archeocs milosz@archeocs.com
//
//Copyright (c) 2010, Miłosz Pigłas, Archeocs
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//
//* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//* Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.Random;

/**
 * Klasa reprezentujaca okreslony uklad na obszarze wielkosci kartki A4
 * @author Milosz Piglas
 *
 */
public class Uklad {
	
	
	private BufferedImage tlo;
	private Macierz mUklad;
	private int poleUklad = 0, sumaRyc = 0, pozIle, pionIle, kwKra = 0;
	private LinkedList<Rycina> ryciny = new LinkedList<Rycina>();
	private LinkedList<String> opis = new LinkedList<String>();
	private int wypik;
	private int szpik,zi = 0;
	private LinkedList<BufferedImage> zapamietane = new LinkedList<BufferedImage>();
	private int szMarg,wskSk07=0;
	public static final int NOWY = 0;
	public static final int ZAPAMIETANY = 1;
	private Permutacja perm;
	public String naglowek = null;
	private String uklTytul = null;
	private int wyOpis;
	
	/**
	 * Konstruktor
	 */
	public Uklad(int szpik, int wypik)
	{
		this.szpik = szpik;
		this.wypik = wypik;
		poleUklad = szpik * wypik;
		double psz = K.itod(szpik);
		double pwy = K.itod(wypik);
		kwKra = Macierz.KRAW_DL;
		pozIle = K.dtoi(Math.floor(psz / kwKra));
		pionIle = K.dtoi(Math.floor(pwy / kwKra));
		wskSk07 = K.dtoi(14 / 25.4 * 90);
		mUklad = new Macierz(pionIle,pozIle);
		perm = new Permutacja();
		
	}
	
	/**
	 * Usuwa z arkusza wszystkie narysowane obrazki
	 */
	private void noweTlo()
	{
		tlo = new BufferedImage(szpik, wypik,BufferedImage.TYPE_INT_ARGB_PRE);
		opis.clear();
	}
	
	/**
	 * Dodaje obrazek do ukladu, nim zostanie znaleziona jego pozycja
	 * @param sciezka
	 * @return
	 */
	public boolean dodajRyc(String sciezka) 
    {
        Rycina tmp = new Rycina(sciezka);
        int poleRyc = tmp.getPole();
        if ((poleRyc+sumaRyc) <= poleUklad)
        {
                ryciny.add(tmp);
                perm.zwieksz();
                sumaRyc += poleRyc;
                return true;
        }
        return false;
    }
	
	/**
	 * Usuwa rycine z ukladu
	 * @param nr numer ryciny
	 * @return
	 */
	public boolean usunRyc(int nr)
    {
        Rycina tmp = ryciny.get(nr);
        sumaRyc -= tmp.getPole();
        ryciny.remove(nr);
        perm.zmniejsz();
        return true;
    }
	
	/**
	 * Okresla szerokosc marginesow arkusza
	 * @param szerokosc
	 */
	public void setMarginesy(int szerokosc)
	{
		szMarg = szerokosc;
	}
	
	/**
	 * Ustawia marginesy arkusza o zadanej szerokosci
	 */
	private void marginesy()
	{
		int piksele = K.dtoi(szMarg / 25.4 * 90 / kwKra);
		int opKw;
		this.wyOpis = 30;
		mUklad.setOne(0, 0,piksele,pionIle);
		mUklad.setOne(0, 0,pozIle,piksele);
		// dolny margines przeznaczony na legende
		if (uklTytul == null)
			opKw = K.dtoi(Math.ceil(K.itod(wyOpis) / 20));
		else
			opKw = K.dtoi(Math.ceil(K.itod(wyOpis+20)/20));
		mUklad.setOne(pionIle-opKw, 1, pozIle-1, opKw);
	}
	
	/**
	 * Dodaje legende do opisow obrazkow
	 */
	private void dodajLegende()
	{
		int ytop = tlo.getHeight()-wyOpis;
		Graphics g = tlo.getGraphics();
		g.setColor(Color.BLACK);
		if (uklTytul != null)
		{
			Font f = g.getFont();
			g.setFont(f.deriveFont(Font.BOLD));
			g.drawString(uklTytul, 200, ytop-20);
			g.setFont(f);
		}
		for (String linia : opis)
		{
			g.drawString(linia, 20, ytop);
			ytop += 15;
		}
		
			
	}
	
	/**
	 * Dodaje opis do obrazka
	 * @param nr numer obrazka
	 * @param opis opis obrazka
	 */
	public void dodajOpisRyc(int nr, String opis)
	{
		Rycina tmp = ryciny.get(nr);
		tmp.setOpis(opis);
		ryciny.set(nr, tmp);
	}
	
	/**
	 * Tworzy nowy uklad, lub przywraca zapamietany
	 * @param rodzaj okresla czy uklad ma byc tworzony na nowo, czy pobrac zapamietany
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public boolean nowyUklad(int rodzaj)
	{
		if (rodzaj == NOWY)
		{
			//LinkedList<Rycina> lockop = (LinkedList<Rycina>) ryciny.clone();
			int dlry = 0,ow=0,nrRyc = 1;
			Image obrazek = null;
			String podpis = null;
			String leglin = "";
			noweTlo();
			Graphics g = tlo.getGraphics();
			g.setColor(Color.BLACK);
			g.drawRect(1, 1, 740, 1050);
			marginesy();
			
			int[] sek = perm.next();
			naglowek = perm.toString();
			//while ((dlry = lockop.size()) > 0)
			for (int i = 0; i < sek.length; i++)
			{
				//int a = los.nextInt(dlry);
				//Rycina r = lockop.get(a);
				//lockop.remove(a);
				int a = sek[i];
				Rycina r = ryciny.get(a);
				int[] obszar = mUklad.getObszar(r.getSz(), r.getWy()+1);
				if (obszar != null)
				{
					mUklad.setOne(obszar[0], obszar[1], r.getSz(), r.getWy()+1);
					int y = obszar[0] * kwKra;
					int x = obszar[1] * kwKra;
					ow = r.getWy() * 20;
					obrazek = r.getObrazek();
					podpis = String.format("%d-%s ", nrRyc,r.getOpis());
					if (r.getOpis() == null)
						podpis = String.format("%d-%s ", nrRyc,r.getNazwa());
					if ((leglin+podpis).length() < 110)
						leglin += podpis;
					else
					{
						opis.add(leglin);
						leglin = podpis;
					}
					g.drawImage(obrazek, x,y, null);
					g.drawString(String.valueOf(nrRyc), x, y+ow+5);
					nrRyc++;
				}
				else
				{
					int skSz = K.dtoi(Math.ceil(r.getSz()*0.7));
					int skWy = K.dtoi(Math.ceil(r.getWy()*0.7));
					int[] skOb = mUklad.getObszar(skSz, skWy+1);
					if (skOb != null)
					{
						mUklad.setOne(skOb[0],skOb[1],skSz,skWy+1);
						int y = skOb[0] * kwKra;
						int x = skOb[1] * kwKra;
						obrazek = r.getObrazek(0.7);
						ow = skWy * 20;
						podpis = String.format("%d-%s ", nrRyc,r.getOpis());
						if (r.getOpis() == null)
							podpis = String.format("%d-%s ", nrRyc,r.getNazwa());
						if ((leglin+podpis).length() < 110)
							leglin += podpis;
						else
						{
							opis.add(leglin);
							leglin = podpis;
						}
						g.drawImage(obrazek, x,y, null);
						g.drawString(String.valueOf(nrRyc), x, y+5+ow);
						g.drawLine(x+10, y+3+ow, x+10+wskSk07, y+3+ow);
						g.drawLine(x+10+(wskSk07/2), y+1+ow,x+10+(wskSk07/2),y+3+ow);
						nrRyc++;
					}
				}
				
			}
			opis.add(leglin);
			dodajLegende();
			mUklad.zeruj();
			return true;
		}
		else if (rodzaj == ZAPAMIETANY)
		{
			if (zi == zapamietane.size())
				zi = 0;
			tlo = zapamietane.get(zi);
			zi++;
			return true;
				
		}
		return false;
	}
	
	/**
	 * Zapamietuje obrazek do pozniejszego ponownego uzycia
	 */
	public void zapamietaj()
	{
		BufferedImage tmp = tlo.getSubimage(0, 0, tlo.getWidth(), tlo.getHeight());
		zapamietane.add(tmp);
	}
	
	/**
	 * Zwraca wygenerowany uklad obrazkow narysowany na arkuszu
	 * @return
	 */
	public BufferedImage getNowy()
	{
		return tlo;
	}

	public void setTytul(String tytul) {
		// TODO Auto-generated method stub
		uklTytul = tytul;
	}

}
